package com.thghh.ch5.group;

import java.util.*;

/**
 * @author Zhikang.Peng
 * @version 1.0
 * @email thghh@qq.com
 * @date 2020/10/23 11:06
 */
public class GroupTree<K extends Comparable<K>, V> {

    private TreeMap<K, GroupEntry<K, V>> treeMap;

    public GroupTree() {
        treeMap = new TreeMap<>();
    }

    public V put(K key, V value) {
        GroupEntry<K, V> p = new GroupEntry(key, value, null);
        GroupEntry<K, V> oldValue = treeMap.put(key, p);
        return oldValue.value;
    }

    public V get(K key) {
        GroupEntry<K, V> p = treeMap.get(key);
        return p.value;
    }

    public void addChild(K parent, K child) {
        addChild(parent, null, child, null);
    }

    public List<GroupEntry<K, V>> getChilds(K key) {
        GroupEntry<K, V> p = treeMap.get(key);
        return p.childs;
    }

    public Set<Map.Entry<K, GroupEntry<K, V>>> getIterator() {
        return treeMap.entrySet();
    }

    public void addChild(K parent, V parentValue, K child, V childVlue) {
        GroupEntry<K, V> p = treeMap.get(parent);
        GroupEntry<K, V> c = treeMap.get(child);

        if (p == null) {
            p = new GroupEntry<>(parent, parentValue, null);
            treeMap.put(parent, p);
        } else if (parentValue != null) {
            p.setValue(parentValue);
        }

        if (c == null) {
            c = new GroupEntry<>(child, childVlue, p);
            treeMap.put(child, c);
        } else if (childVlue != null) {
            c.setValue(childVlue);
        }

        c.parent = p;
        p.childs.add(c);
    }


    static final boolean valEquals(Object o1, Object o2) {
        return (o1 == null ? o2 == null : o1.equals(o2));
    }

    public static final class GroupEntry<K, V> implements Map.Entry<K, V> {
        K key;
        V value;
        GroupEntry<K, V> parent;
        List<GroupEntry<K, V>> childs;

        GroupEntry(K key, V value, GroupEntry<K, V> parent) {
            this.key = key;
            this.value = value;
            this.parent = parent;
            childs = new LinkedList<>();
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        public Iterator<GroupEntry<K, V>> getChildIterator() {
            return childs.iterator();
        }

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;

            return valEquals(key, e.getKey()) && valEquals(value, e.getValue());
        }

        public int hashCode() {
            int keyHash = (key == null ? 0 : key.hashCode());
            int valueHash = (value == null ? 0 : value.hashCode());
            return keyHash ^ valueHash;
        }

        public String toString() {
            return key + "=" + value;
        }
    }


}
